/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frstat_system.c                                    */
/*  NOTE      =                                                    */
/*  DATE      = 2015/01/14 by guojq                                */
/*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include <json-c/json.h>

#include "frcomm.h"
#include "frmem.h"
#include "frlog.h"
#include "frlist.h"
#include "frhash2.h"
#include "frame.h"
#include "frame_params.h"
#include "frmodule_mng.h"
#include "frtask_mng.h"
#include "frstat_module.h"
#include "frreport_mng.h"
#include "frstat_pkg.h"

extern unsigned long g_ul_pcap_queue_used;

#define SYSTEM_STAT_HASH_SIZE   100

//conn_data 连接信息
typedef struct __conn_data_status {
    unsigned long ul_syn_conns;
    unsigned long ul_established_conns;
    unsigned long ul_disconnect_conns;
    unsigned long ul_not_active_conns;
    unsigned long ul_destroy_conns;
} conn_data_status;

typedef struct __conn_data_avg {
    unsigned long ul_syn_conns[4];
    unsigned long ul_established_conns[4];
    unsigned long ul_disconnect_conns[4];
} conn_data_avg;

typedef struct __conn_data {
    conn_data_status st_conn_data_total;
    conn_data_avg    st_conn_data_avg;
} conn_data;

//session_data session信息
typedef struct __session_data_status {
    unsigned long ul_login;
    unsigned long ul_logout;
} session_data_status;

typedef struct __session_data_avg {
    unsigned long ul_login[4];
    unsigned long ul_logout[4];
} session_data_avg;

typedef struct __session_data {
    session_data_status st_session_data_total;
    session_data_avg st_session_data_avg;
} session_data;

//总模块信息
typedef struct __module_stat {
    int  i_l7_proto;
    char *p_module_name;
    
    conn_data       st_conn_data;
    session_data    st_session_data;
} module_stat;

//总体的 包速率、流量、连接数
typedef struct __conn_stat {
    unsigned long ul_packets;   //数据包总数
    unsigned long ul_bytes;     //总流量
    unsigned long ul_conns;     //总连接数
    unsigned long ul_drops;     //总丢包数
} conn_stat;

typedef struct __conn_stat_avg {
    unsigned long ul_packets[4];//数据包总数
    unsigned long ul_bytes[4];  //总流量
    unsigned long ul_conns[4];  //总连接数
    unsigned long ul_drops[4];  //总丢包数
} conn_stat_avg;

//总体运行信息
typedef struct __system_stat {
    struct timeval start_time;  //程序开始运行时间
    unsigned int ui_memory;     //内存
    int i_pthreads;             //线程数
    
    conn_stat st_conn_total;    //总连接信息
    conn_stat_avg st_conn_avg;  //平均总连接信息

    Frhash_header st_module_stat;      //模块信息hash
    
    int last_time;              //毫秒
} system_stat;

FR_STATIC system_stat g_st_system;
FR_STATIC pthread_rwlock_t g_system_stat_system_rwlock;
//做取平均值的间隔时间
FR_STATIC int g_i_interval_stat_system = 1;
FR_STATIC int g_i_flag_init_stat_system = FR_FAIL;

/*******************************************************************************
*  FUNC     :  释放节点
*  ARGS     :  p_node          
*  RTN      :  
*  NOTE     :
*******************************************************************************/
FR_STATIC void __stat_system_node_free(Frlist_node* p_node)
{
    module_stat *p_stat_node = NULL;
    
    if (p_node && p_node->data)
    {
        p_stat_node = (module_stat *)p_node->data;
        if(p_stat_node->p_module_name)
            frfree(p_stat_node->p_module_name);
        frfree(p_stat_node);
    }
}

/*******************************************************************************
*  FUNC     :  计算平均值
*  ARGS     :  arr_ul_last          总数表
*           :  p_avg                算好的平均值
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
FR_STATIC void __stat_system_count_avg(unsigned long arr_ul_last[4], unsigned long *p_avg)
{
    if (arr_ul_last[0] == 0 || arr_ul_last[1] == 0)
    {
        //记录的是总数，因此前2个节点为0的情况说明平均为0或者是刚开始统计，平均设成0
        *p_avg = 0;
        return;
    }
    if (arr_ul_last[2] == 0)
    {
        *p_avg = (arr_ul_last[0] - arr_ul_last[1])/g_i_interval_stat_system;
        return;
    }
    if (arr_ul_last[3] == 0)
    {
        *p_avg = (arr_ul_last[0] - arr_ul_last[2])/(g_i_interval_stat_system*2);
        return;
    }
    *p_avg = (arr_ul_last[0] - arr_ul_last[3])/(g_i_interval_stat_system*3);
    return;
}

/*******************************************************************************
*  FUNC     :  计算平均值
*  ARGS     :  p_node           当前节点
*           :  p_data           
*  RTN      :  1   (成功)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __stat_system_frmodule_count(Frlist_node* p_node, const void *p_data)
{
    module_stat *p_st_list_stat = NULL;
    
    p_st_list_stat = (module_stat *)p_node->data;
    
    memmove(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_syn_conns + 1, p_st_list_stat->st_conn_data.st_conn_data_avg.ul_syn_conns, sizeof(unsigned long)*3);
    memmove(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_established_conns + 1, p_st_list_stat->st_conn_data.st_conn_data_avg.ul_established_conns, sizeof(unsigned long)*3);
    memmove(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_disconnect_conns + 1, p_st_list_stat->st_conn_data.st_conn_data_avg.ul_disconnect_conns, sizeof(unsigned long)*3);

    //记录的为总数
    p_st_list_stat->st_conn_data.st_conn_data_avg.ul_syn_conns[0] = p_st_list_stat->st_conn_data.st_conn_data_total.ul_syn_conns;
    p_st_list_stat->st_conn_data.st_conn_data_avg.ul_established_conns[0] = p_st_list_stat->st_conn_data.st_conn_data_total.ul_established_conns;
    p_st_list_stat->st_conn_data.st_conn_data_avg.ul_disconnect_conns[0] = p_st_list_stat->st_conn_data.st_conn_data_total.ul_disconnect_conns;
    
    memmove(p_st_list_stat->st_session_data.st_session_data_avg.ul_login + 1, p_st_list_stat->st_session_data.st_session_data_avg.ul_login, sizeof(unsigned long)*3);
    memmove(p_st_list_stat->st_session_data.st_session_data_avg.ul_logout + 1, p_st_list_stat->st_session_data.st_session_data_avg.ul_logout, sizeof(unsigned long)*3);
    
    p_st_list_stat->st_session_data.st_session_data_avg.ul_login[0] = p_st_list_stat->st_session_data.st_session_data_total.ul_login;
    p_st_list_stat->st_session_data.st_session_data_avg.ul_logout[0] = p_st_list_stat->st_session_data.st_session_data_total.ul_logout;
    
    return 1;
}

/*******************************************************************************
*  FUNC     :  计算平均值
*  ARGS     :           
*  RTN      :  
*  NOTE     :
*******************************************************************************/
void frstat_system_count(void)
{
    if(g_i_flag_init_stat_system == FR_FAIL)
        return;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);

    memmove(g_st_system.st_conn_avg.ul_packets + 1, g_st_system.st_conn_avg.ul_packets, sizeof(unsigned long)*3);
    memmove(g_st_system.st_conn_avg.ul_bytes + 1, g_st_system.st_conn_avg.ul_bytes, sizeof(unsigned long)*3);
    memmove(g_st_system.st_conn_avg.ul_conns + 1, g_st_system.st_conn_avg.ul_conns, sizeof(unsigned long)*3);
    memmove(g_st_system.st_conn_avg.ul_drops + 1, g_st_system.st_conn_avg.ul_drops, sizeof(unsigned long)*3);

    g_st_system.st_conn_avg.ul_packets[0] = g_st_system.st_conn_total.ul_packets;
    g_st_system.st_conn_avg.ul_bytes[0] = g_st_system.st_conn_total.ul_bytes;
    g_st_system.st_conn_avg.ul_conns[0] = g_st_system.st_conn_total.ul_conns;
    g_st_system.st_conn_avg.ul_drops[0] = g_st_system.st_conn_total.ul_drops;

    frhash2_run(&g_st_system.st_module_stat, NULL, __stat_system_frmodule_count);
    
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    return;
}

FR_STATIC void __frmodule_stat_show(Frlist_node* p_node, char *p_outbuff, unsigned int ui_outlen)
{
    module_stat *p_st_list_stat = NULL;
    unsigned long ul_syn_avg = 0;
    unsigned long ul_established_avg = 0;
    unsigned long ul_disconnect_avg = 0;
    unsigned long ul_login_avg = 0;
    unsigned long ul_logout_avg = 0;

    unsigned long ul_request = 0;
    unsigned long ul_response = 0;
    unsigned long ul_success = 0;
    unsigned long ul_failed = 0;
    unsigned long ul_request_avg = 0;
    unsigned long ul_response_avg = 0;
    unsigned long ul_success_avg = 0;
    unsigned long ul_failed_avg = 0;
    
    p_st_list_stat = (module_stat *)p_node->data;
    
    __stat_system_count_avg(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_syn_conns, &ul_syn_avg);
    __stat_system_count_avg(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_established_conns, &ul_established_avg);
    __stat_system_count_avg(p_st_list_stat->st_conn_data.st_conn_data_avg.ul_disconnect_conns, &ul_disconnect_avg);

    __stat_system_count_avg(p_st_list_stat->st_session_data.st_session_data_avg.ul_login, &ul_login_avg);
    __stat_system_count_avg(p_st_list_stat->st_session_data.st_session_data_avg.ul_logout, &ul_logout_avg);

    frstat_module_get_info(p_st_list_stat->i_l7_proto, &ul_request, &ul_response, &ul_success, &ul_failed
                        , &ul_request_avg, &ul_response_avg, &ul_success_avg, &ul_failed_avg);

    snprintf(p_outbuff, ui_outlen
            , "module:%d(%s)\n"
              "\tConn_data:     connect:%lu(%lu/s)\tdisconnect:%lu(%lu/s)\tinactive:%lu\tdestroy:%lu\n"
              "\tSession_data:  login:%lu(%lu/s)\tlogout=%lu(%lu/s)\n"
              "\tL7_data:       request:%lu(%lu/s)\tresponse:%lu(%lu/s)\tsuccess:%lu(%lu/s)\tfailed:%lu(%lu/s)\n"
            , p_st_list_stat->i_l7_proto, p_st_list_stat->p_module_name
            , p_st_list_stat->st_conn_data.st_conn_data_total.ul_established_conns, ul_established_avg
            , p_st_list_stat->st_conn_data.st_conn_data_total.ul_disconnect_conns, ul_disconnect_avg
            , p_st_list_stat->st_conn_data.st_conn_data_total.ul_not_active_conns
            , p_st_list_stat->st_conn_data.st_conn_data_total.ul_destroy_conns
            , p_st_list_stat->st_session_data.st_session_data_total.ul_login, ul_login_avg
            , p_st_list_stat->st_session_data.st_session_data_total.ul_logout, ul_logout_avg
            , ul_request, ul_request_avg
            , ul_response, ul_response_avg
            , ul_success, ul_success_avg
            , ul_failed, ul_failed_avg);
    return;
}


FR_STATIC void __frstat_date(char *p_buff, unsigned int ui_size, struct tm *p_tm)
{
    if(p_buff == NULL || ui_size <= 1 || p_tm == NULL)
        return;

    snprintf(p_buff, ui_size, "%04d-%02d-%02dT%02d:%02d:%02d"
            , p_tm->tm_year + 1900,p_tm->tm_mon + 1,p_tm->tm_mday
            , p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec);
    return;
}

void frstat_system_info(json_object *p_st_json)
{
    if(p_st_json == NULL)
        return;

    char arr_buff[128];
    struct   timeval  st_timeval_now;
    time_t   st_time_now;
    struct tm *p_tm = NULL;

    //通用信息
    json_object_object_add(p_st_json, "dataVersion",json_object_new_string("1.0.0"));
    json_object_object_add(p_st_json, "serviceName",json_object_new_string("apm_broker 1.0"));
    json_object_object_add(p_st_json, "processID",json_object_new_int(getpid()));

    p_tm = localtime(&g_st_system.start_time.tv_sec);
    arr_buff[0] = '\0';
    __frstat_date(arr_buff, sizeof(arr_buff), p_tm);
    json_object_object_add(p_st_json, "processStart",json_object_new_string(arr_buff));

    time(&st_time_now);
    p_tm = localtime(&st_time_now);
    arr_buff[0] = '\0';
    __frstat_date(arr_buff, sizeof(arr_buff), p_tm);
    json_object_object_add(p_st_json, "systemTime",json_object_new_string(arr_buff));

    gettimeofday(&st_timeval_now, 0);
    json_object_object_add(p_st_json, "processRunTime", json_object_new_int64(st_timeval_now.tv_sec - g_st_system.start_time.tv_sec));

    json_object_object_add(p_st_json, "threads",json_object_new_int( frame_threads_cnt() ));

#if FR_MEM_STAT
    __fr_memstat_info_all_json(p_st_json);
#endif

    //框架信息
    json_object *p_st_json_sub;
    p_st_json_sub = json_object_new_object();
    if(p_st_json_sub == NULL)
        return;

    //业务信息
    json_object_object_add(p_st_json_sub, "rxPackets", json_object_new_int64( g_st_system.st_conn_total.ul_packets ));
    json_object_object_add(p_st_json_sub, "rxBytes", json_object_new_int64( g_st_system.st_conn_total.ul_bytes ));
    json_object_object_add(p_st_json_sub, "connects", json_object_new_int64( g_st_system.st_conn_total.ul_conns ));
    //json_object_object_add(p_st_json_sub, "dropPackets", json_object_new_int64( g_st_system.st_conn_total.ul_drops ));
    json_object_object_add(p_st_json_sub, "queueCounts", json_object_new_int64( g_ul_pcap_queue_used ));
    json_object_object_add(p_st_json_sub, "queueSize", json_object_new_int(st_apm_params.ui_ct_data_pkgs) );

    json_object_object_add(p_st_json, "frame", p_st_json_sub);

    //网卡抓包信息
    frstat_pkg_count_json(p_st_json);

    //report
    frreport_stat_json(p_st_json);

    return;
}

/*******************************************************************************
*  FUNC     :  总体运行情况打印
*  ARGS     :  pp_result            总体运行情况
*  RTN      :  
*  NOTE     :  pp_result需要外面释放
*******************************************************************************/
void frstat_system_output(char **pp_result)
{
    char arr_system[128], arr_conns[256], arr_pkg[256], arr_report[512];
    char *p_outbuff=NULL;
    unsigned long ul_pps = 0;
    unsigned long ul_bps = 0;
    unsigned long ul_conns_avg = 0;
    unsigned long ul_drops_avg = 0;
    struct tm *p_tm = NULL;

    if(g_i_flag_init_stat_system == FR_FAIL)
        return ;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);

    p_tm = localtime(&g_st_system.start_time.tv_sec);

    g_st_system.i_pthreads = frame_threads_cnt();
    //系统信息
    #if FR_MEM_STAT
        g_st_system.ui_memory = fr_slab_all_used();
        snprintf(arr_system, sizeof(arr_system), "start:   %04d/%02d/%02d  %02d:%02d:%02d\nSystem:  mem=%u(%.2fM) threads=%d\n"
               , p_tm->tm_year + 1900,p_tm->tm_mon + 1,p_tm->tm_mday
               , p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec
               , g_st_system.ui_memory, g_st_system.ui_memory/1024.0/1024.0, g_st_system.i_pthreads);
    #else
        snprintf(arr_system, sizeof(arr_system), "start:   %04d/%02d/%02d  %02d:%02d:%02d\nSystem:  threads=%d\n"
               , p_tm->tm_year + 1900,p_tm->tm_mon + 1,p_tm->tm_mday
               , p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec
               , g_st_system.i_pthreads);
    #endif

    //总连接数信息
    __stat_system_count_avg(g_st_system.st_conn_avg.ul_packets, &ul_pps);
    __stat_system_count_avg(g_st_system.st_conn_avg.ul_bytes, &ul_bps);
    __stat_system_count_avg(g_st_system.st_conn_avg.ul_conns, &ul_conns_avg);
    __stat_system_count_avg(g_st_system.st_conn_avg.ul_drops, &ul_drops_avg);
    
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    snprintf(arr_conns, sizeof(arr_conns)
           , "         packets:%lu(%lu/s)\tbytes:%lu(%lu/s)\tconns:%lu(%lu/s)\tdrops:%lu(%lu/s)\n"
             "         ct_in_task:%d\tqueue:%lu\n"
           , g_st_system.st_conn_total.ul_packets, ul_pps
           , g_st_system.st_conn_total.ul_bytes, ul_bps
           , g_st_system.st_conn_total.ul_conns, ul_conns_avg
           , g_st_system.st_conn_total.ul_drops, ul_drops_avg
           , frtaskskb_counts()
           , g_ul_pcap_queue_used);

    //接到包信息
    arr_pkg[0] = '\0';
    frstat_pkg_info(arr_pkg, sizeof(arr_pkg));
    //上报信息统计
    arr_report[0]='\0';
    frreport_stat(arr_report, sizeof(arr_report));

    //每个模块的信息
    pthread_rwlock_rdlock(&g_system_stat_system_rwlock);
    frhash2_show_all2(&g_st_system.st_module_stat, &p_outbuff, __frmodule_stat_show);
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    if(pp_result == NULL)
    {
        printf("%s%s%s%s\n%s\n", arr_system, arr_conns, arr_pkg, arr_report, p_outbuff ? p_outbuff : "");
    }
    else
    {
        char *p_out = NULL;
        int i_outlen = strlen(arr_system) + strlen(arr_conns) + strlen(arr_pkg) + strlen(arr_report) +4;

        i_outlen += p_outbuff ? strlen(p_outbuff) : 0;
        //2= '\n\0'
        p_out = (char *)frmalloc(i_outlen + 2);
        if (p_out == NULL)
            return;
        snprintf(p_out, i_outlen + 2, "%s%s%s%s\n%s\n", arr_system, arr_conns, arr_pkg, arr_report, p_outbuff ? p_outbuff : "");
        *pp_result = p_out;
    }
    if (p_outbuff)
        frfree(p_outbuff);
    
    return;
}

/*******************************************************************************
*  FUNC     :  总体运行情况更新
*  ARGS     :  i_packages           包数量
*              i_bytes              字节数
*              i_conns              连接数
*  RTN      :  
*  NOTE     :  
*******************************************************************************/
void frstat_system_add(int i_packages, int i_bytes, int i_conns, int i_drops)
{
    if(g_i_flag_init_stat_system == FR_FAIL)
        return;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);
    
    g_st_system.st_conn_total.ul_packets += i_packages;
    g_st_system.st_conn_total.ul_bytes += i_bytes;
    g_st_system.st_conn_total.ul_conns += i_conns;
    g_st_system.st_conn_total.ul_drops += i_drops;

    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    return;
}

/*******************************************************************************
*  FUNC     :  增加module的session信息
*  ARGS     :  i_l7_proto       模块l7名
*           :  ui_login         登录个数
*           :  ui_logout        登出个数
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
int frstat_system_module_session_add(int i_l7_proto, unsigned int ui_login, unsigned int ui_logout)
{
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_new_node = NULL;
    module_stat *p_st_new_module_data = NULL;

    if(g_i_flag_init_stat_system == FR_FAIL)
        return FR_FAIL;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);
    p_st_node = frhash2_getLong(&g_st_system.st_module_stat, i_l7_proto);
    if (p_st_node)
    {
        module_stat *p_st_list_stat = (module_stat *)p_st_node->data;
        p_st_list_stat->st_session_data.st_session_data_total.ul_login += ui_login;
        p_st_list_stat->st_session_data.st_session_data_total.ul_logout += ui_logout;
        
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_SUCC;
    }
    //添加新模块
    p_st_new_module_data = (module_stat *) frmalloc(sizeof(module_stat));
    if (p_st_new_module_data == NULL)
    {
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    
    memset(p_st_new_module_data, 0x00, sizeof(module_stat));
    {
        Frmodule_mng *p_st_module = frmodule_get_module(i_l7_proto);
        if(p_st_module && p_st_module->p_st_l7_module->p_module_name)
            p_st_new_module_data->p_module_name = frstrdup(p_st_module->p_st_l7_module->p_module_name);
        else
            p_st_new_module_data->p_module_name = frstrdup(" ");
    }
    p_st_new_module_data->i_l7_proto = i_l7_proto;
    p_st_new_module_data->st_session_data.st_session_data_total.ul_login = ui_login;
    p_st_new_module_data->st_session_data.st_session_data_total.ul_logout = ui_logout;
    
    p_st_new_node = frlist_node_create(p_st_new_module_data);
    if (p_st_new_node == NULL)
    {
        frfree(p_st_new_module_data->p_module_name);
        frfree(p_st_new_module_data);
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    frhash2_addLong(&g_st_system.st_module_stat, i_l7_proto, p_st_new_node);
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  增加module的not_active信息
*  ARGS     :  i_l7_proto       模块l7名
*           :  i_inactive_cnt   不活跃连接数
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
int frstat_system_module_inactive_add(int i_l7_proto, int i_inactive_cnt)
{
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_new_node = NULL;
    module_stat *p_st_new_module_data = NULL;

    if(g_i_flag_init_stat_system == FR_FAIL)
        return FR_FAIL;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);
    p_st_node = frhash2_getLong(&g_st_system.st_module_stat, i_l7_proto);
    if (p_st_node)
    {
        module_stat *p_st_list_stat = (module_stat *)p_st_node->data;

        p_st_list_stat->st_conn_data.st_conn_data_total.ul_not_active_conns += i_inactive_cnt;
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);

        return FR_SUCC;
    }
    if (i_inactive_cnt < 0)
    {
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    //添加新模块
    p_st_new_module_data = (module_stat *) frmalloc(sizeof(module_stat));
    if (p_st_new_module_data == NULL)
    {
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }

    memset(p_st_new_module_data, 0x00, sizeof(module_stat));
    {
        Frmodule_mng *p_st_module = frmodule_get_module(i_l7_proto);
        if(p_st_module && p_st_module->p_st_l7_module->p_module_name)
            p_st_new_module_data->p_module_name = frstrdup(p_st_module->p_st_l7_module->p_module_name);
        else
            p_st_new_module_data->p_module_name = frstrdup(" ");
    }
    p_st_new_module_data->i_l7_proto = i_l7_proto;
    p_st_new_module_data->st_conn_data.st_conn_data_total.ul_not_active_conns = i_inactive_cnt;

    p_st_new_node = frlist_node_create(p_st_new_module_data);
    if (p_st_new_node == NULL)
    {
        frfree(p_st_new_module_data);
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    frhash2_addLong(&g_st_system.st_module_stat, i_l7_proto, p_st_new_node);
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  增加module的conn信息
*  ARGS     :  i_l7_proto       模块l7名
*           :  i_syn           syn连接数
*           :  i_established   tcp握手成功数
*           :  i_disconnect    断开连接数
*           :  i_destroy       连接终止个数
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
int frstat_system_module_conn_add(int i_l7_proto, int i_syn, int i_established
                                , int i_disconnect, int i_destroy)
{
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_new_node = NULL;
    module_stat *p_st_new_module_data = NULL;

    if(g_i_flag_init_stat_system == FR_FAIL)
        return FR_FAIL;
    
    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);
    p_st_node = frhash2_getLong(&g_st_system.st_module_stat, i_l7_proto);
    if (p_st_node)
    {
        module_stat *p_st_list_stat = (module_stat *)p_st_node->data;

        if ((i_syn < 0 && i_syn + p_st_list_stat->st_conn_data.st_conn_data_total.ul_syn_conns < 0)
        || (i_established < 0 && i_established + p_st_list_stat->st_conn_data.st_conn_data_total.ul_established_conns < 0)
        || (i_disconnect < 0 && i_disconnect + p_st_list_stat->st_conn_data.st_conn_data_total.ul_disconnect_conns < 0)
        || (i_destroy < 0 && i_destroy + p_st_list_stat->st_conn_data.st_conn_data_total.ul_destroy_conns < 0))
        {
            FRLOG_WARN_DETAIL("conn_data total < 0!");
            return FR_FAIL;
        }

        p_st_list_stat->st_conn_data.st_conn_data_total.ul_syn_conns += i_syn;
        p_st_list_stat->st_conn_data.st_conn_data_total.ul_established_conns += i_established;
        p_st_list_stat->st_conn_data.st_conn_data_total.ul_disconnect_conns += i_disconnect;
        p_st_list_stat->st_conn_data.st_conn_data_total.ul_destroy_conns += i_destroy;
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        
        return FR_SUCC;
    }
    if (i_syn < 0 || i_established < 0 || i_disconnect < 0 || i_destroy < 0)
    {
        FRLOG_WARN_DETAIL("conn_data total < 0!");
        return FR_FAIL;
    }
    //添加新模块
    p_st_new_module_data = (module_stat *) frmalloc(sizeof(module_stat));
    if (p_st_new_module_data == NULL)
    {
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    
    memset(p_st_new_module_data, 0x00, sizeof(module_stat));

    {
        Frmodule_mng *p_st_module = frmodule_get_module(i_l7_proto);
        if(p_st_module && p_st_module->p_st_l7_module && p_st_module->p_st_l7_module->p_module_name)
            p_st_new_module_data->p_module_name = frstrdup(p_st_module->p_st_l7_module->p_module_name);
        else
            p_st_new_module_data->p_module_name = frstrdup(" ");
    }

    p_st_new_module_data->i_l7_proto = i_l7_proto;
    p_st_new_module_data->st_conn_data.st_conn_data_total.ul_syn_conns = i_syn;
    p_st_new_module_data->st_conn_data.st_conn_data_total.ul_established_conns = i_established;
    p_st_new_module_data->st_conn_data.st_conn_data_total.ul_disconnect_conns = i_disconnect;
    p_st_new_module_data->st_conn_data.st_conn_data_total.ul_destroy_conns = i_destroy;
    
    p_st_new_node = frlist_node_create(p_st_new_module_data);
    if (p_st_new_node == NULL)
    {
        frfree(p_st_new_module_data->p_module_name);
        frfree(p_st_new_module_data);
        pthread_rwlock_unlock(&g_system_stat_system_rwlock);
        return FR_FAIL;
    }
    frhash2_addLong(&g_st_system.st_module_stat, i_l7_proto, p_st_new_node);
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  初始化system的信息
*  ARGS     :  i_interval       平均间隔时间
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
int frstat_system_init(int i_interval)
{
    g_i_interval_stat_system = i_interval;
    memset(&g_st_system, 0x00, sizeof(system_stat));

    if (pthread_rwlock_init(&g_system_stat_system_rwlock, NULL) != 0)
    {
        FRLOG_ERROR_DETAIL("pthread_rwlock_init failed");
        return FR_FAIL;
    }
    
    if (frhash2_create(&g_st_system.st_module_stat, SYSTEM_STAT_HASH_SIZE) != FR_SUCC)
    {
        FRLOG_ERROR_DETAIL("frhash2_create failed");
        return FR_FAIL;
    }
    
    gettimeofday(&g_st_system.start_time, 0);
    g_i_flag_init_stat_system = FR_SUCC;
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放资源
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_system_destroy(void)
{
    if(g_i_flag_init_stat_system == FR_FAIL)
        return;

    pthread_rwlock_wrlock(&g_system_stat_system_rwlock);
    frhash2_free(&g_st_system.st_module_stat, __stat_system_node_free);
    pthread_rwlock_unlock(&g_system_stat_system_rwlock);
    
    pthread_rwlock_destroy(&g_system_stat_system_rwlock);

    g_i_flag_init_stat_system = FR_FAIL;
    return;
}

